# coding: utf-8

import ezdxf
import xml.etree.ElementTree as ET


def svg_to_dxf(svg_file, dxf_file, scale_factor=0.5):
    doc = ezdxf.new(dxfversion="R2010")
    msp = doc.modelspace()

    # Ensure the SimSun font is defined in the DXF
    if "SimSun" not in doc.styles:
        doc.styles.add("SimSun", font="simsun.ttf")

    tree = ET.parse(svg_file)
    root = tree.getroot()
    namespaces = {"svg": "http://www.w3.org/2000/svg"}

    circles = []

    def process_circle(circle, dx=0, dy=0):
        cx = float(circle.get("cx")) + dx
        cy = float(circle.get("cy")) + dy
        r = float(circle.get("r"))
        msp.add_circle((cx, cy), r)
        circles.append((cx, cy, r))

    def process_text(text, dx=0, dy=0):
        x = float(text.get("x")) + dx
        y = float(text.get("y")) + dy
        content = text.text
        font_size = float(text.get("font-size", 24)) * scale_factor

        # Find the nearest circle center and adjust position
        nearest_circle = min(circles, key=lambda c: ((x - c[0]) ** 2 + (y - c[1]) ** 2))
        cx, cy, r = nearest_circle
        adjusted_x = cx - 16
        adjusted_y = cy - font_size / 3

        msp.add_text(
            content,
            dxfattribs={
                "height": font_size,
                "insert": (adjusted_x, adjusted_y),
                "style": "SimSun",
                "rotation": 0,
            },
        )

    def process_polyline(polyline, dx=0, dy=0):
        points = polyline.get("points").strip().split(" ")
        points = [
            (float(x) + dx, float(y) + dy)
            for x, y in (point.split(",") for point in points)
        ]
        msp.add_lwpolyline(points)

    def process_polygon(polygon, dx=0, dy=0):
        points = polygon.get("points").strip().split(" ")
        points = [
            (float(x) + dx, float(y) + dy)
            for x, y in (point.split(",") for point in points)
        ]
        msp.add_lwpolyline(points, close=True)

    def process_line(line, dx=0, dy=0):
        x1 = float(line.get("x1")) + dx
        y1 = float(line.get("y1")) + dy
        x2 = float(line.get("x2")) + dx
        y2 = float(line.get("y2")) + dy
        msp.add_line((x1, y1), (x2, y2))

    def process_rect(rect, dx=0, dy=0):
        x = float(rect.get("x")) + dx
        y = float(rect.get("y")) + dy
        width = float(rect.get("width"))
        height = float(rect.get("height"))
        msp.add_lwpolyline(
            [(x, y), (x + width, y), (x + width, y + height), (x, y + height), (x, y)]
        )

    def process_element(element, dx=0, dy=0):
        if element.tag.endswith("circle"):
            process_circle(element, dx, dy)
        elif element.tag.endswith("text"):
            process_text(element, dx, dy)
        elif element.tag.endswith("polyline"):
            process_polyline(element, dx, dy)
        elif element.tag.endswith("polygon"):
            process_polygon(element, dx, dy)
        elif element.tag.endswith("line"):
            process_line(element, dx, dy)
        elif element.tag.endswith("rect"):
            process_rect(element, dx, dy)

    # Process elements directly under the root
    for element in root:
        if element.tag.endswith("g"):
            continue
        process_element(element)

    # Process <g> elements with transform and their children
    for g in root.findall(".//svg:g", namespaces):
        transform = g.get("transform")
        dx, dy = 0, 0
        if transform and "translate" in transform:
            translate = transform.strip().lstrip("translate(").rstrip(")").split(",")
            if len(translate) == 2:
                dx, dy = float(translate[0]), float(translate[1])

        for element in g:
            process_element(element, dx, dy)

    doc.saveas(dxf_file)


if __name__ == "__main__":
    # Example call with scale_factor to reduce the text size
    svg_to_dxf("小图.svg", "小图_crosssuoxiao.dxf", scale_factor=0.8)
